import re
import uuid
import sys
import os
import argparse
from markdown import Markdown
from pygments import highlight
from pygments.lexers import get_lexer_by_name
from pygments.formatters import HtmlFormatter
from pygments.util import ClassNotFound
from bs4 import BeautifulSoup

def generate_id():
    return "code-" + str(uuid.uuid4())[:8]

def escape_html(text):
    return text.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")

def highlight_code(code, lang):
    try:
        lexer = get_lexer_by_name(lang, stripall=True)
    except ClassNotFound:
        lexer = get_lexer_by_name('text', stripall=True)
    
    formatter = HtmlFormatter(style='default', cssclass="highlight", linenos=False)
    return highlight(code, lexer, formatter)

def generate_code_html(lang, highlighted_code, raw_code):
    """生成代码块的HTML结构"""
    code_id = generate_id()
    escaped_code = escape_html(raw_code)
    
    return f'''
<div class="code-container">
    <div class="code-header">
        <span class="code-language">{lang}</span>
        <button class="copy-btn" onmouseenter="animateButton(this)" onclick="copyCode('{code_id}', this)">复制</button>
    </div>
    {highlighted_code}
    <pre id="{code_id}" style="display: none;">{escaped_code}</pre>
</div>
    ''', code_id

def process_custom_blocks(md_content):
    # 统一的区块处理函数
    def process_block(block_type, content):
        # 先递归处理内容中的其他区块
        content = process_all_blocks(content)
        
        # 提取代码块并替换为占位符
        content, code_blocks = extract_code_blocks(content)
        
        # 转换Markdown内容
        md = Markdown(extensions=['tables'])
        html_content = md.convert(content)
        
        # 替换回代码块
        html_content = replace_code_blocks(html_content, code_blocks)
        
        # 根据区块类型返回对应的HTML包装
        if block_type == "green":
            return f'<div class="green">\n{html_content}\n</div>'
        elif block_type == "orange":
            return f'<div class="orange">\n{html_content}\n</div>'
        elif block_type == "red":
            return f'<div class="red">\n{html_content}\n</div>'
        elif block_type == "list":
            # 特性列表特殊处理 - 直接包装在feature-list中
            return f'<div class="feature-list">\n{html_content}\n</div>'
        elif block_type == "ul":
            # 无序列表特殊处理
            soup = BeautifulSoup(html_content, 'html.parser')
            items = []
            for li in soup.find_all('li'):
                items.append(f'<li>{li.get_text().strip()}</li>')
            return f'<ul>\n{"".join(items)}\n</ul>'
        elif block_type == "item":
            # 直接作为特性项处理
            return f'<div class="feature-item" onmouseover="animateFeature(this)" onmouseout="resetFeature(this)">\n{html_content}\n</div>'
    
    # 递归处理所有区块
    def process_all_blocks(content):
        # 定义区块类型和对应的正则表达式
        block_types = {
            "green": r'###block_green_start\n([\s\S]*?)\n###block_green_end',
            "orange": r'###block_orange_start\n([\s\S]*?)\n###block_orange_end',
            "red": r'###block_red_start\n([\s\S]*?)\n###block_red_end',
            "list": r'###block_list_start\n([\s\S]*?)\n###block_list_end',
            "ul": r'###block_ul_start\n([\s\S]*?)\n###block_ul_end',
            "item": r'###block_item_start\n([\s\S]*?)\n###block_item_end'
        }
        
        # 按顺序处理所有区块类型
        for block_type, pattern in block_types.items():
            def replace(match):
                inner_content = match.group(1)
                return process_block(block_type, inner_content)
                
            content = re.sub(pattern, replace, content)
        
        return content
    
    # 提取代码块并替换为占位符
    def extract_code_blocks(content):
        code_blocks = []
        def replace_with_placeholder(match):
            lang = match.group(1) or 'text'
            code = match.group(2)
            block_id = f"CODE_BLOCK_{len(code_blocks)}"
            code_blocks.append((lang, code))
            return f"@@@CODE_BLOCK_PLACEHOLDER_{block_id}@@@"
        
        content = re.sub(r'```(\w*)\n([\s\S]*?)\n```', replace_with_placeholder, content)
        return content, code_blocks
    
    # 将占位符替换为处理好的代码块
    def replace_code_blocks(content, code_blocks):
        for i, (lang, code) in enumerate(code_blocks):
            placeholder = f"@@@CODE_BLOCK_PLACEHOLDER_CODE_BLOCK_{i}@@@"
            if placeholder in content:
                highlighted_code = highlight_code(code, lang)
                code_html, _ = generate_code_html(lang, highlighted_code, code)
                content = content.replace(placeholder, code_html)
        return content
    
    # 开始处理
    return process_all_blocks(md_content)

def process_markdown(md_content):
    # 处理代码块
    def handle_code_block(match):
        lang = match.group(1) or 'text'
        code = match.group(2)
        highlighted_code = highlight_code(code, lang)
        code_html, _ = generate_code_html(lang, highlighted_code, code)
        return code_html
    
    md_content = re.sub(
        r'```(\w*)\n([\s\S]*?)\n```',
        handle_code_block,
        md_content
    )
    
    # 再处理自定义区块
    md_content = process_custom_blocks(md_content)
    
    # 转换其他Markdown内容
    md = Markdown(extensions=['tables'])
    html_content = md.convert(md_content)
    
    return html_content

def generate_html_template(content, title="API文档"):
    return f'''<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{title}</title>
    <style>
        /* 添加中文字体优化 */
        @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@300;400;500;700&display=swap');
        
        :root {{
            --primary-color: #3498db;
            --secondary-color: #2980b9;
            --text-color: #333;
            --bg-color: #f9f9f9;
            --code-bg: #f0f0f0;
            --border-color: #ddd;
            --success-color: #2ecc71;
            --warning-color: #f39c12;
            --error-color: #e74c3c;
            --hover-shadow: 0 8px 16px rgba(0,0,0,0.1);
            --active-shadow: 0 4px 8px rgba(0,0,0,0.15);
        }}
        
        @media (prefers-color-scheme: dark) {{
            :root {{
                --primary-color: #5dade2;
                --secondary-color: #3498db;
                --text-color: #ecf0f1;
                --bg-color: #2c3e50;
                --code-bg: #34495e;
                --border-color: #7f8c8d;
                --hover-shadow: 0 8px 16px rgba(0,0,0,0.3);
                --active-shadow: 0 4px 8px rgba(0,0,0,0.4);
            }}
        }}
        
        body {{
            font-family: 'Noto Sans SC', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            line-height: 1.8;
            color: var(--text-color);
            background-color: var(--bg-color);
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
            text-rendering: optimizeLegibility;
            -webkit-font-smoothing: antialiased;
            -moz-osx-font-smoothing: grayscale;
        }}
        /* 添加中文段落优化 */
        p {{
            margin: 1.2em 0;
            text-align: justify;
            letter-spacing: 0.02em;
        }}
        img {{
            max-width: 100%;
            height: auto;
            border-radius: 8px;
            box-shadow: 0 4px 8px rgba(0,0,0,0.1);
            transition: all 0.3s ease;
            margin: 15px 0;
            display: block;
        }}

        img:hover {{
            transform: scale(1.02);
            box-shadow: 0 6px 12px rgba(0,0,0,0.15);
        }}

        .image-container {{
            text-align: center;
            margin: 20px 0;
        }}

        .image-caption {{
            font-style: italic;
            color: #666;
            margin-top: 8px;
            font-size: 0.9em;
        }}
        .code-header {{
            display: flex;
            justify-content: space-between;
            align-items: center;
            background-color: rgba(0,0,0,0.1);
            padding: 5px 10px;
            border-radius: 5px 5px 0 0;
            font-size: 0.8em;
        }}
        
        .code-language {{
            color: var(--text-color);
            opacity: 0.8;
            font-weight: bold;
        }}
        
        .copy-btn {{
            background-color: var(--primary-color);
            color: white;
            border: none;
            padding: 3px 8px;
            border-radius: 3px;
            cursor: pointer;
            font-size: 0.7em;
            transition: all 0.3s ease;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }}
        
        .copy-btn:hover {{
            transform: translateY(-2px);
            box-shadow: var(--hover-shadow);
        }}
        
        .copy-btn:active {{
            transform: translateY(0);
            box-shadow: var(--active-shadow);
        }}

        /* 优化代码字体 */
        pre, code, .highlight {{
            font-family: 'Fira Code', 'Consolas', 'Monaco', 'Andale Mono', 'Noto Sans SC', monospace;
            font-size: 0.95em;
            line-height: 1.5;
            -webkit-font-smoothing: antialiased;
            -moz-osx-font-smoothing: grayscale;
        }}
        
        pre {{
            padding: 15px;
            overflow-x: auto;
            border-radius: 0 0 5px 5px;
            border-left: 4px solid var(--primary-color);
            tab-size: 4;
            background-color: var(--code-bg);
            margin: 0;
        }}
        
        /* 优化代码高亮区域 */
        .highlight {{
            background-color: var(--code-bg);
            border-radius: 0 0 5px 5px;
            padding: 0;
            margin: 0;
        }}
        
        /* 优化代码容器 */
        .code-container {{
            position: relative;
            margin: 20px 0;
            border-radius: 5px;
            box-shadow: 0 4px 8px rgba(0,0,0,0.1);
            background-color: var(--code-bg);
            overflow: hidden;
            transition: transform 0.3s ease;
        }}
        
        .code-container:hover {{
            transform: translateY(-3px);
            box-shadow: var(--hover-shadow);
        }}
        
        .back-to-top {{
            position: fixed;
            bottom: 30px;
            right: 30px;
            background-color: var(--primary-color);
            color: white;
            width: 50px;
            height: 50px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            opacity: 0;
            visibility: hidden;
            transition: all 0.3s ease;
            box-shadow: 0 2px 10px rgba(0,0,0,0.2);
            z-index: 100;
            animation: pulse 2s infinite;
        }}
        
        .back-to-top.show {{
            opacity: 1;
            visibility: visible;
        }}
        
        .back-to-top:hover {{
            transform: scale(1.1);
            animation: none;
        }}
        
        h1, h2, h3 {{
            color: var(--primary-color);
            margin-top: 1.5em;
            transition: all 0.3s ease;
        }}
        
        h1:hover, h2:hover, h3:hover {{
            transform: translateX(5px);
        }}
        
        h1 {{
            border-bottom: 2px solid var(--primary-color);
            padding-bottom: 10px;
        }}
        
        code {{
            font-family: 'Consolas', 'Courier New', monospace;
            background-color: var(--code-bg);
            padding: 2px 5px;
            border-radius: 3px;
            transition: all 0.2s;
        }}
        
        code:hover {{
            background-color: rgba(0,0,0,0.1);
        }}
        
        .green {{
            background-color: #e8f8f5;
            border-left: 4px solid var(--success-color);
            padding: 15px;
            margin: 20px 0;
            border-radius: 0 5px 5px 0;
            transition: all 0.3s ease;
        }}
        
        .green:hover {{
            transform: translateX(5px);
        }}
        
        .orange {{
            background-color: #fff8e6;
            border-left: 4px solid var(--warning-color);
            padding: 15px;
            margin: 20px 0;
            border-radius: 0 5px 5px 0;
            transition: all 0.3s ease;
        }}
        
        .orange:hover {{
            transform: translateX(5px);
        }}
        
        .red {{
            background-color: #ffebee;
            border-left: 4px solid var(--error-color);
            padding: 15px;
            margin: 20px 0;
            border-radius: 0 5px 5px 0;
            transition: all 0.3s ease;
        }}
        
        .red:hover {{
            transform: translateX(5px);
        }}
        
        table {{
            width: 100%;
            border-collapse: collapse;
            margin: 15px 0;
        }}
        
        th, td {{
            border: 1px solid var(--border-color);
            padding: 8px 12px;
            text-align: left;
            transition: all 0.2s;
        }}
        
        tr:hover td {{
            background-color: rgba(0,0,0,0.05);
            transform: translateY(-1px);
        }}
        
        th {{
            background-color: var(--primary-color);
            color: white;
        }}
        
        .feature-list {{
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
            gap: 15px;
            margin: 20px 0;
        }}
        
        .feature-item {{
            background-color: rgba(255,255,255,0.1);
            padding: 15px;
            border-radius: 5px;
            box-shadow: 0 2px 5px rgba(0,0,0,0.05);
            transition: all 0.3s ease;
            transform: translateY(0);
            cursor: pointer;
            border: 1px solid rgba(0,0,0,0.05);
        }}
        
        .feature-item:hover {{
            transform: translateY(-5px) scale(1.02);
            box-shadow: var(--hover-shadow);
            background-color: rgba(255,255,255,0.15);
            z-index: 2;
        }}
        
        .feature-item:active {{
            transform: translateY(-2px) scale(1.01);
            box-shadow: var(--active-shadow);
        }}
        
        ul {{
            padding-left: 20px;
        }}
        
        li {{
            margin: 5px 0;
            transition: all 0.2s;
        }}
        
        li:hover {{
            transform: translateX(5px);
        }}
        
        @media (max-width: 768px) {{
            body {{
                padding: 10px;
            }}
            
            .feature-list {{
                grid-template-columns: 1fr;
            }}
            
            .back-to-top {{
                width: 40px;
                height: 40px;
                bottom: 20px;
                right: 20px;
            }}
        }}
        
        pre {{ line-height: 125%; }}
        td.linenos .normal {{ color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }}
        span.linenos {{ color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }}
        td.linenos .special {{ color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }}
        span.linenos.special {{ color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }}
        .highlight .hll {{ background-color: #ffffcc }}
        .highlight {{ background: #f8f8f8; }}
        .highlight .c {{ color: #3D7B7B; font-style: italic }}
        .highlight .err {{ border: 1px solid #F00 }}
        .highlight .k {{ color: #008000; font-weight: bold }}
        .highlight .o {{ color: #666 }}
        .highlight .ch {{ color: #3D7B7B; font-style: italic }}
        .highlight .cm {{ color: #3D7B7B; font-style: italic }}
        .highlight .cp {{ color: #9C6500 }}
        .highlight .cpf {{ color: #3D7B7B; font-style: italic }}
        .highlight .c1 {{ color: #3D7B7B; font-style: italic }}
        .highlight .cs {{ color: #3D7B7B; font-style: italic }}
        .highlight .gd {{ color: #A00000 }}
        .highlight .ge {{ font-style: italic }}
        .highlight .ges {{ font-weight: bold; font-style: italic }}
        .highlight .gr {{ color: #E40000 }}
        .highlight .gh {{ color: #000080; font-weight: bold }}
        .highlight .gi {{ color: #008400 }}
        .highlight .go {{ color: #717171 }}
        .highlight .gp {{ color: #000080; font-weight: bold }}
        .highlight .gs {{ font-weight: bold }}
        .highlight .gu {{ color: #800080; font-weight: bold }}
        .highlight .gt {{ color: #04D }}
        .highlight .kc {{ color: #008000; font-weight: bold }}
        .highlight .kd {{ color: #008000; font-weight: bold }}
        .highlight .kn {{ color: #008000; font-weight: bold }}
        .highlight .kp {{ color: #008000 }}
        .highlight .kr {{ color: #008000; font-weight: bold }}
        .highlight .kt {{ color: #B00040 }}
        .highlight .m {{ color: #666 }}
        .highlight .s {{ color: #BA2121 }}
        .highlight .na {{ color: #687822 }}
        .highlight .nb {{ color: #008000 }}
        .highlight .nc {{ color: #00F; font-weight: bold }}
        .highlight .no {{ color: #800 }}
        .highlight .nd {{ color: #A2F }}
        .highlight .ni {{ color: #717171; font-weight: bold }}
        .highlight .ne {{ color: #CB3F38; font-weight: bold }}
        .highlight .nf {{ color: #00F }}
        .highlight .nl {{ color: #767600 }}
        .highlight .nn {{ color: #00F; font-weight: bold }}
        .highlight .nt {{ color: #008000; font-weight: bold }}
        .highlight .nv {{ color: #19177C }}
        .highlight .ow {{ color: #A2F; font-weight: bold }}
        .highlight .w {{ color: #BBB }}
        .highlight .mb {{ color: #666 }}
        .highlight .mf {{ color: #666 }}
        .highlight .mh {{ color: #666 }}
        .highlight .mi {{ color: #666 }}
        .highlight .mo {{ color: #666 }}
        .highlight .sa {{ color: #BA2121 }}
        .highlight .sb {{ color: #BA2121 }}
        .highlight .sc {{ color: #BA2121 }}
        .highlight .dl {{ color: #BA2121 }}
        .highlight .sd {{ color: #BA2121; font-style: italic }}
        .highlight .s2 {{ color: #BA2121 }}
        .highlight .se {{ color: #AA5D1F; font-weight: bold }}
        .highlight .sh {{ color: #BA2121 }}
        .highlight .si {{ color: #A45A77; font-weight: bold }}
        .highlight .sx {{ color: #008000 }}
        .highlight .sr {{ color: #A45A77 }}
        .highlight .s1 {{ color: #BA2121 }}
        .highlight .ss {{ color: #19177C }}
        .highlight .bp {{ color: #008000 }}
        .highlight .fm {{ color: #00F }}
        .highlight .vc {{ color: #19177C }}
        .highlight .vg {{ color: #19177C }}
        .highlight .vi {{ color: #19177C }}
        .highlight .vm {{ color: #19177C }}
        .highlight .il {{ color: #666 }}
        
        @keyframes pulse {{
            0% {{ transform: scale(1); }}
            50% {{ transform: scale(1.05); }}
            100% {{ transform: scale(1); }}
        }}
    </style>
</head>
<body>
    {content}
    
    <div class="back-to-top" id="backToTop" onmouseover="animateBackToTop(this)" onmouseout="resetBackToTop(this)">↑</div>
    
    <script>
        const backToTopBtn = document.getElementById('backToTop');
        
        window.addEventListener('scroll', () => {{
            if (window.pageYOffset > 300) {{
                backToTopBtn.classList.add('show');
            }} else {{
                backToTopBtn.classList.remove('show');
            }}
        }});
        
        backToTopBtn.addEventListener('click', () => {{
            window.scrollTo({{
                top: 0,
                behavior: 'smooth'
            }});
        }});
        
        function copyCode(id, btn) {{
            const codeElement = document.getElementById(id);
            const textArea = document.createElement('textarea');
            textArea.value = codeElement.textContent;
            document.body.appendChild(textArea);
            textArea.select();
            
            try {{
                const successful = document.execCommand('copy');
                if(successful) {{
                    // 添加动画效果
                    btn.textContent = '已复制!';
                    btn.style.backgroundColor = '#2ecc71';
                    setTimeout(() => {{
                        btn.textContent = '复制';
                        btn.style.backgroundColor = '';
                        // 修复：重置位置和阴影
                        btn.style.transform = '';
                        btn.style.boxShadow = '';
                    }}, 2000);
                }}
            }} catch(err) {{
                console.error('复制失败:', err);
            }}
            
            document.body.removeChild(textArea);
        }}
        
        // 动画效果函数
        function animateButton(btn) {{
            btn.style.transform = 'translateY(-3px)';
            btn.style.boxShadow = '0 4px 8px rgba(0,0,0,0.2)';
        }}
        
        // 添加按钮重置函数
        function resetButton(btn) {{
            btn.style.transform = '';
            btn.style.boxShadow = '';
        }}
        
        function animateFeature(item) {{
            item.style.transform = 'translateY(-5px) scale(1.02)';
            item.style.boxShadow = '0 8px 16px rgba(0,0,0,0.1)';
            item.style.zIndex = '2';
        }}
        
        function resetFeature(item) {{
            item.style.transform = '';
            item.style.boxShadow = '';
            item.style.zIndex = '';
        }}
        
        function animateBackToTop(btn) {{
            btn.style.transform = 'scale(1.1)';
            btn.style.backgroundColor = '#2ecc71';
        }}
        
        function resetBackToTop(btn) {{
            btn.style.transform = '';
            btn.style.backgroundColor = '';
        }}
    </script>
</body>
</html>
'''

def convert_markdown_to_html(input_file, output_file):
    try:
        with open(input_file, 'r', encoding='utf-8') as f:
            md_content = f.read()
        
        # 提取标题
        title = "API文档"
        first_line = md_content.split('\n')[0]
        if first_line.startswith('# '):
            title = first_line[2:].strip()
        
        html_content = process_markdown(md_content)
        full_html = generate_html_template(html_content, title)
        
        with open(output_file, 'w', encoding='utf-8') as f:
            f.write(full_html)
        
        print(f"成功将 {input_file} 转换为 {output_file}")
    except Exception as e:
        print(f"转换失败: {str(e)}")
        sys.exit(1)

if __name__ == "__main__":
    # 创建命令行解析器
    parser = argparse.ArgumentParser(
        description='Markdown转HTML工具 - 支持代码高亮和自定义区块',
        epilog='示例: python mdapi2html.py input.md output.html'
    )
    
    # 添加命令行参数（使用位置参数）
    parser.add_argument('input', nargs='?', 
                        help='输入Markdown文件路径')
    parser.add_argument('output', nargs='?',
                        help='输出HTML文件路径')
    
    # 解析命令行参数
    args = parser.parse_args()
    
    # 如果提供了命令行参数
    if args.input and args.output:
        input_file = args.input
        output_file = args.output
    else:
        # 否则使用交互式输入
        print("请提供输入和输出文件路径")
        print("用法: python mdapi2html.py [输入文件] [输出文件]")
        print("或直接输入路径:")
        input_file = input("输入文件路径(如: input.md): ").strip()
        output_file = input("输出文件路径(如: output.html): ").strip()
    
    # 检查输入文件是否存在
    if not os.path.exists(input_file):
        print(f"错误: 输入文件 {input_file} 不存在")
        sys.exit(1)
    
    # 执行转换
    convert_markdown_to_html(input_file, output_file)
